package com.amiu.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


public class MapUtil {

	public static void printMap(Map<?, ?> map){
		for (Object key : map.keySet()) {
			System.out.println(map.get(key));
		}
	}
	
	/**
	 * 将map的value转换为List
	 */
	public static <T> List<T> toListValue(Map<?,T> map){
		List<T> list = new ArrayList<T>();
		for (Object key : map.keySet()) {
			list.add(map.get(key));
		}
		return list;
	}
	/**
	 * 将map的key转换为List
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> toListKey(Map<T,?> map){
		List<T> list = new ArrayList<T>();
		for (Object key : map.keySet()) {
			list.add((T) key);
		}
		return list;
	}
	
	@SuppressWarnings("unchecked")
	/**
	 * 获取map值中的对象V的字段field的值，将其存入Set<T>;注意：map的value应该为统一类型
	 * field 需要获取的字段值
	 * Exception 字段field的get方法错误
	 */
	public static <T, V> Set<T> toSet(Map<?,V> map,String field) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Set<T> sets = new HashSet<T>();
		String methodName = toGetMethod(field);
		Class<? extends Object> clazz = null; 
		Method method=null;//获取methodName为名字的方法，如：getAddress()
		
		for (Object key : map.keySet()) {
			try {
				if(clazz == null)//只获取一次
					clazz = map.get(key).getClass();
				if(method == null)
					method = clazz.getDeclaredMethod(methodName);
			} catch (NoSuchMethodException e) {
				throw new NoSuchMethodException("没有方法： "+ methodName);
			}
			
			Object target = map.get(key);//获取对象，如User(假如map装的是Map<id,User>)
			T t = (T) method.invoke(target);//运行方法获取字段值，如 user.getAddress();
			sets.add(t);
		}
		return sets;
	}
	
	
	@SuppressWarnings("unchecked")
	public static <T> Map<Long,T> toLongMap(List<T> listTarget,String field) throws Exception{
		Map<Long, T> resultMap = new HashMap<Long, T>();
		
		String methodName = toGetMethod(field);
		Class<? extends Object> clazz =listTarget.get(1).getClass();
		for (T target : listTarget) {
			Method method;
			try {
				method = clazz.getDeclaredMethod(methodName);
			} catch (NoSuchMethodException e) {
				throw new Exception("没有方法： "+ methodName);
			}
			long key = (long) method.invoke(target);
			if(resultMap.containsKey(key)) throw new Exception("有相同的"+field);
			resultMap.put(key, target);
		}
		return resultMap;
	}
	
	public static <T> Map<Integer,T> toIntMap(List<T> listTarget,String field) throws Exception{
		Map<Integer, T> resultMap = new HashMap<Integer, T>();
		String methodName = toGetMethod(field);
		Class<? extends Object> clazz =listTarget.get(1).getClass();
		for (T target : listTarget) {
			Method method;
			try {
				method = clazz.getDeclaredMethod(methodName);
			} catch (NoSuchMethodException e) {
				throw new Exception("没有方法： "+ methodName);
			}
			int key = (int) method.invoke(target);
			if(resultMap.containsKey(key)) throw new Exception("有相同的"+field);
			resultMap.put(key, target);
		}
		return resultMap;
	}
	
	public static <T> Map<String,T> toStringMap(List<T> listTarget,String field) throws Exception{
		Map<String, T> resultMap = new HashMap<String, T>();
		String methodName = toGetMethod(field);
		Class<? extends Object> clazz =listTarget.get(1).getClass();
		for (T target : listTarget) {
			Method method;
			try {
				method = clazz.getDeclaredMethod(methodName);
			} catch (NoSuchMethodException e) {
				throw new Exception("没有方法： "+ methodName);
			}
			String key = (String) method.invoke(target);
			if(resultMap.containsKey(key)) throw new Exception("有相同的"+field);
			resultMap.put(key, target);
		}
		return resultMap;
	}
	
	/**
	 * 获取get方法名字，如：getId
	 * @param field 需要获取的字段名,如：id
	 * @return 方法名，如：getId
	 */
	private static String toGetMethod(String field){
		return "get"+toUpperStart(field);
	}
	private static String toUpperStart(String str){
		return str.substring(0,1).toUpperCase() + str.substring(1);
	}
//	
//	public static void printIf(Map<?, ?> map){
//		for (Object o : map.keySet()) {
//			System.out.println(map.get(o));
//		}
//	}
}
